﻿using Furion.DynamicApiController;
using Furion.FriendlyException;
using Gear.Application.Service.File;
using Gear.Core.Result;
using Gear.NoSql.Core;
using Gear.NoSql.Core.Mongo;
using Gear.NoSql.Core.Tool;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using MongoDB.Bson;
using System;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Gear.Application.Service.File
{

    /// <summary>
    /// Mongo文件
    /// </summary>
    [DynamicApiController]
    [ApiDescriptionSettings("MongoFile")]
    public class MongoService
    {
        private HttpContext _httpContext;

        public MongoService(IHttpContextAccessor httpContextAccessor)
        {
            _httpContext = httpContextAccessor.HttpContext;
        }
        /// <summary>
        /// 上传
        /// </summary>
        /// <param name="options">文件附加内容</param>
        /// <param name="files">文件</param>
        /// <returns></returns>
        public BaseResult FileUploadRecord([FromForm] List<string> options, [FromForm] List<IFormFile> files)
        {
            BaseResult result = new BaseResult();
            try
            {
                if(options.Count!= files.Count) throw Oops.Oh("请确认附加参数是否与文件数量保持一致！");
                List<MetaFlies> metaflies = new List<MetaFlies>();
                if (files.Count == 0) throw Oops.Oh("未能找到可上传文件！");
                int j = 0;
                foreach (var fromFile in files)
                {
                    var fs = fromFile.OpenReadStream();
                    MemoryStream ms = new MemoryStream();
                    fs.CopyTo(ms);
                    ms.Position = 0;
                    metaflies.Add(new MetaFlies
                    {
                        file = ms,
                        metaflie = new MetaFlie
                        {
                            dbtype = "",
                            dbuser = "",
                            source = "",
                            update = DateTime.Now.ToString(),
                            subjoin = options[j].ToString(),
                            filetype = fromFile.ContentType,
                            suffix = NoSqlTool.GetSuffix(fromFile.FileName),
                            autonym = NoSqlTool.GetAntonym(fromFile.FileName)
                        }
                    });
                    j++;
                }
                result.data = FileHelper.Upload(metaflies);
                result.success = true;

                
            }
            catch (Exception ex)
            {
                result.message = ex.Message;
            }
            return result;
        }

        /// <summary>
        /// 上传-记录附件
        /// </summary>
        /// <param name="options">文件附加内容</param>
        /// <param name="files">文件</param>
        /// <param name="pkvalue">目标主键</param>
        /// <param name="tablename">目标表</param>
        /// <returns></returns>
        public BaseResult FileUploadRecord([FromForm] List<string> options, [FromForm] List<IFormFile> files,string pkvalue,string tablename)
        {
            BaseResult result = new BaseResult();
            try
            {
                if (options.Count != files.Count) throw Oops.Oh("请确认附加参数是否与文件数量保持一致！");
                List<MetaFlies> metaflies = new List<MetaFlies>();
                if (files.Count == 0) throw Oops.Oh("未能找到可上传文件！");
                int j = 0;
                foreach (var fromFile in files)
                {
                    var fs = fromFile.OpenReadStream();
                    MemoryStream ms = new MemoryStream();
                    fs.CopyTo(ms);
                    ms.Position = 0;
                    metaflies.Add(new MetaFlies
                    {
                        file = ms,
                        metaflie = new MetaFlie
                        {
                            dbtype = "",
                            dbuser = "",
                            source = "",
                            update = DateTime.Now.ToString(),
                            subjoin = options[j].ToString(),
                            filetype = fromFile.ContentType,
                            suffix = NoSqlTool.GetSuffix(fromFile.FileName),
                            autonym = NoSqlTool.GetAntonym(fromFile.FileName)
                        }
                    });
                    j++;
                }
                result.data = FileHelper.AttachmentRecord(FileHelper.Upload(metaflies),pkvalue,tablename);
                result.success = true;


            }
            catch (Exception ex)
            {
                result.message = ex.Message;
            }
            return result;
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="fileid">文件id</param>
        /// <returns></returns>
        public BaseResult FileDelete(string fileid)
        {
            BaseResult result = new BaseResult();
            try
            {
                result.data = FileHelper.Delete(fileid);
                result.success = true;
            }
            catch (Exception ex)
            {
                result.message = ex.Message;
            }
            return result;
        }

        /// <summary>
        /// 图像显示
        /// </summary>
        /// <param name="fileid">文件id</param>
        [HttpGet]
        public void PicShow(string fileid)
        {
            try
            {
                MemoryStream str = new ();
                MemoryStream ms = new();

                var type = FileHelper.ReadStream(fileid, str);
                ImageFormat format = ImageFormat.Bmp;
                if (type == "image/jpeg")
                    format = ImageFormat.Jpeg;
                else if (type == "image/png")
                    format = ImageFormat.Png;
                else if (type == "image/gif")
                    format = ImageFormat.Gif;
                else if (type == "image/gif")
                    format = ImageFormat.Icon;
                else
                    throw new Exception("无效的类型");
                System.Drawing.Bitmap map = new System.Drawing.Bitmap(str);
                map.Save(ms, format);
                //Response.ClearContent();
                _httpContext.Response.ContentType = type;
                //Response.BinaryWrite(ms.ToArray());
                _httpContext.Response.Body.WriteAsync(ms.ToArray());
            }
            catch (Exception)
            {
                return;
            }

        }

        /// <summary>
        /// 缩略图显示
        /// </summary>
        /// <param name="fileid">文件id</param>
        [HttpGet]
        public void ThumbShow(string fileid)
        {
            try
            {
                System.IO.MemoryStream ms = new System.IO.MemoryStream();

                var streamtype = FileHelper.ReadStream_Thumb(fileid);
                ImageFormat format = ImageFormat.Bmp;
                if (streamtype.type == "image/jpeg")
                    format = ImageFormat.Jpeg;
                else if (streamtype.type == "image/png")
                    format = ImageFormat.Png;
                else if (streamtype.type == "image/gif")
                    format = ImageFormat.Gif;
                else if (streamtype.type == "image/gif")
                    format = ImageFormat.Icon;
                else
                    throw new Exception("无效的类型");
                System.Drawing.Bitmap map = new System.Drawing.Bitmap(streamtype.stream);
                map.Save(ms, format);
                //Response.ClearContent();
                _httpContext.Response.ContentType = streamtype.type;
                //Response.BinaryWrite(ms.ToArray());
                _httpContext.Response.Body.WriteAsync(ms.ToArray());
            }
            catch (Exception)
            {
                return;
            }

        }

        /// <summary>
        /// 音视频播放
        /// </summary>
        /// <param name="fileid">文件id</param>
        [HttpGet]
        public void VideoShow(string fileid)
        {
            //var buffer = FileHelper.Read(fileid);
            var reqRange = _httpContext.Request.Headers["Range"].ToString();
            string[] reqBlockRange = null;
            if (!string.IsNullOrEmpty(reqRange))
            {
                reqBlockRange = reqRange.Replace("bytes=", "").Split('-');
            }
            _httpContext.Response.StatusCode = 206;
            _httpContext.Response.Headers.Add("status", "206");
            _httpContext.Response.Headers.Add("accept-ranges", "bytes");
            _httpContext.Response.Headers.Add("access-control-allow-methods", "HEAD, GET, OPTIONS");
            _httpContext.Response.Headers.Add("access-control-allow-origin", "*");
            _httpContext.Response.Headers.Add("cache-control", "public, max-age=30726563");
            //Response.Headers.Add("content-disposition", $"attachment;  filename=test.mp4");
            _httpContext.Response.ContentType = FileHelper.GetFileType(fileid);
            MemoryStream ms = new MemoryStream();
            FileHelper.ReadStream(fileid, ms);
            using (var stream = ms)
            using (var reader = new BinaryReader(stream))
            {
                long fileSize = stream.Length;

                long startPosition = 0;
                long partialSize = fileSize;
                if (reqBlockRange != null)
                {
                    //startPosition = Convert.ToInt32(reqBlockRange[0]);
                    //partialSize = fileSize - startPosition;
                    //safari 
                    startPosition = Convert.ToInt64(reqBlockRange[0]);
                    if (reqBlockRange.Length > 1)
                    {
                        long endPosition = fileSize;
                        if (long.TryParse(reqBlockRange[1], out endPosition))
                        {
                            partialSize = endPosition - startPosition + 1;
                        }
                    }
                    else
                    {
                        // chrome 等
                        partialSize = fileSize - startPosition;
                    }
                }
                //将部分内容读入具有指定大小的缓冲区
                byte[] newbuffer = new byte[(int)partialSize];
                //转到+偏移地址
                reader.BaseStream.Seek(startPosition, SeekOrigin.Begin);

                //填充缓冲区从开始的地址到地址+块
                reader.Read(newbuffer, 0, (int)partialSize);
                _httpContext.Response.Headers.Add("content-range", $"bytes {startPosition}-{/*startPosition + */partialSize - 1}/{fileSize}");
                _httpContext.Response.Headers.Add("Content-Length", $"{partialSize}");
                //Response.BinaryWrite(newbuffer);
                _httpContext.Response.Body.WriteAsync(newbuffer);
            }
        }

    }
}
